#ifndef _PLAYER_BASE_H_
#define _PLAYER_BASE_H_

#include "Define.h"
#include "Header.h"
#include "Utils.h"
#include "ActivityConfig.h"
#include "msg_errno.h"
#include "msg_public.h"
#include "msg_dbcommon.h"
#include "msg_common.h"
#include <string>
#include <map>

#define ADDI_STATUS_OFFLINE         0x01
#define ADDI_STATUS_TRUSTEESHIP     0x02

#define ACTION_INVALID              (-1)

#define STATE_WIN   1
#define STATE_DRAW  0
#define STATE_LOST  -1

class CHall;
class CRoomBase; 
class CPlayerBase
{
public:
    friend class CHall;
    friend class CRoomBase;
	enum EPlayerState
	{
		E_PlayerState_Idle,			// 对象未被使用
		E_PlayerState_Hall,			// 在大厅中
		E_PlayerState_WaitInRoom,	// 在房间中，未准备
		E_PlayerState_Ready,		// 在房间中，已准备
		E_PlayerState_Gaming,		// 在房间中，正在游戏
	};
    
    struct HandCard
    {
        std::vector<unsigned char> _cards;
        s8 _type;
    };

	CPlayerBase();
	virtual ~CPlayerBase();

	virtual CPlayerBase* Clone(){ return NULL; }
    virtual void Init();
	virtual void OnEnterHall(){}
	virtual void OnLeaveHall(){}
	virtual void OnEnterRoom(){}
	virtual void OnLeaveRoom(){}
	virtual void OnSitDown(){}
	virtual void OnStandUp(){}
    virtual bool OnBreakEnterHall(const std::string &token)
    {
        return false;
    }
    virtual void OnActionTimeOut(s32 action){}
    virtual s32 CanCreateRoom(const std::string &data)
    {
        return errorcode::E_ErrorCode_Success;
    }
    virtual void OnCreateRoom(s32 roomid, const std::string &data){}

	u64 GateId() const;
	u64 ClientId() const;
	u64 UserId() const;
	EPlayerState State() const;
	void SetState(EPlayerState state);
	void InitPlayer(u64 gateid, u64 clientid, u64 userid);
	void ResetPlayer(u64 gateid, u64 clientid);
	void SendMsg(s32 msgid, const IMessage &msg);
    void Close();

	void EnterRoom(CRoomBase &room, s32 seatno);
	void DoLeaveRoom();
	void LeaveRoom();
    void SitDown(s32 seatno);
    void StandUp();
	CRoomBase* GetRoom();
	s32 GetSeatNo();
    void ResetSeatNo(s32 seatno);
    bool IsBeholder();
    void SetOffline(bool offline);
    void SetTrusteeship(bool trusteeship);
    bool IsOffline();
    bool IsTrusteeship();
    bool IsRobot();
    u64 GetOfflineTime() { return m_offlineTime; }
    s32 GetOfflineInterval() { return (s32)(TIME_NOW-m_offlineTime); }
    bool HasReady() { return (State() == CPlayerBase::E_PlayerState_Ready); }

    void SetAction(s32 action, u64 actionExpire);
	s32 GetAction();
	bool IsActionValid();
    void CleanAction();
	s32 GetActionLeftSec();
    void ResetActionExpire(u64 actionExpire);
    virtual bool IsActionTimeOut(u64 now);
    virtual void ActionTimeOut();

    void AddMoreAction(s32 action, u64 actionExpire);
    void DelMoreAction(s32 action);
    bool HasMoreAction(s32 action);
    void CheckMoreActionTimeOut(u64 now);
    void DumpAllActions(std::vector<publicproto::ActionData> &actions);

	u32 AddiStatus(){ return m_addiStatus; };

	void SetReadyExpire(u64 readyExpire);
	bool IsReadyExpire(u64 now);

    void LoginResult(dbcommon::DBUserBasicInfo &basicinfo, publicproto::GameData &gamedata);
    publicproto::UserBasicInfo& GetBasicInfo(){ return m_basicInfo; }
    publicproto::GameData& GetGameData(){ return m_gamedata; }
    void UpdateMoney(s32 type, s64 count, s32 reason);
    void DoUpdateMoney(s32 type, s64 count);
    s64 GetMoney(s32 type);

    s32 GetCurScore() { return m_curScore; }
    void SetCurScore(s32 score) { m_curScore = score; }
    s64 GetAllScore() { return m_allScore; }
    void SetAllScore(s64 score) { m_allScore = score; }

    void SetChannel(const char *channel) { m_channel = channel; }
    std::string& GetChannel() { return m_channel; }
    void ClearActiviyData() { m_activityData.clear(); m_dirtyData.clear(); }
    publicproto::ActivityData* GetActivityData(s32 aid);
    void InitActivityData(std::vector<publicproto::ActivityData> &adata, bool isend);
    void NotifyActivityProgress();
    void InitItems(std::vector<publicproto::ItemInfo> &items, bool isend);
    void GameEndCheckActivity();
    void GameWin(s32 iswin, s64 windata); // -1:lost 0:draw 1:win
    void FlushUserActivityData();
    void FlushUserGameData();
    void FlushUserActivityData2DB(s32 activityid);
    void FlushUserActivityData2DB(publicproto::ActivityData &data);
    void GetActivityAward(s32 activityid);
    void ClearItemData() { m_items.clear(); }
    publicproto::ItemInfo* GetItem(s32 itemid);
    // data表示item变更数量或小时数
    void UpdateItemData(s32 id, s32 itemclass, s32 data, s32 from, s32 param1=0, s32 param2=0);
    void AddAward(s32 type, s32 val, s32 count, s32 reserve, s32 reason, s32 param1=0, s32 param2=0);
    void ClearGameEndData() { m_gameEndData.clear(); };
    std::vector<s64>& GetGameEndData() { return m_gameEndData; }
    void PushGameEndData(s64 data) { m_gameEndData.push_back(data); }
    void UpdateWinMoneyData(s64 data, bool force=false);
    std::string GetLocation() { return m_locationInfo; }
	s32	IncGameTimes(s32 n = 1) { return m_gameTimes += n; }
	s32 ClearGameTimes() { s32 n = m_gameTimes; m_gameTimes = 0; return n; }
    void SetDismissState(s32 dstate) { m_dismissState = dstate; }
    s32 GetDismissState() { return m_dismissState; }
    void CacheHandCard(unsigned char card);
    void CacheHandCards(char *cards, int count, char type);
    std::vector<HandCard>& GetCacheHandCards() { return m_handcards; }
    void ClearCacheHandCards() { m_handcards.clear(); }

private:
    void _CopyDBUserBasicInfo(dbcommon::DBUserBasicInfo &basicinfo);
    void _DumpUserInfo(std::string &data);
    publicproto::ActivityData* _InitNewActivity(const ActivityItem &config);
    void _TimeOutAgreeDismissFriendRoom();

protected:
    u64 m_gateid;
    u64 m_clientid;

    u64 m_userid;
    EPlayerState m_state;
    CRoomBase *m_room;
    s32 m_seatno;

    // 玩家额外状态如掉线或托管
    u32 m_addiStatus;
    u64 m_offlineTime;

    // 行动数据
    s32 m_action;
    u64 m_actionExpireTime;

    // 准备超时
    u64 m_readyExpireTime;

    // 基本信息
    s32 m_type;
    publicproto::UserBasicInfo m_basicInfo;

    // 渠道号
    std::string m_channel;

    // 活动数据
    std::map<s32, publicproto::ActivityData> m_activityData;
    std::map<s32, s8> m_dirtyData;

    // 游戏内的输赢统计信息
    publicproto::GameData m_gamedata;

    // 道具信息
    std::map<s32, publicproto::ItemInfo> m_items;

    // 对局结算的临时信息
    std::vector<s64> m_gameEndData; // [0]始终用于表示输赢

    // 日赚钱数据
    s64 m_winData;
    s32 m_getDate;
    s32 m_winCount;

    // 更多action
    std::map<s32, u64> m_moreAction;

    // 输赢分, 业务层自行使用
    s32 m_curScore; // 当局(上一局)的输赢分
    s64 m_allScore; // 累积输赢分

    std::string m_locationInfo;

    //对局次数，更新到数据库时会清空
    s32 m_gameTimes;
    u64 m_useItemLastTime;

    // 解散房间时玩家的选择状态
    s32 m_dismissState;

    // 缓存玩家手牌及牌型(如果有),各游戏发牌后初始化,便于活动中使用相关数据
    std::vector<HandCard> m_handcards;
};

#endif
